"""
操作录制系统
记录用户操作并支持回放和脚本生成
"""

import json
import time
import threading
from typing import Any, Dict, List, Optional
from dataclasses import dataclass, asdict
from enum import Enum


class OperationType(Enum):
    """操作类型枚举"""
    MOUSE_CLICK = "mouse_click"
    MOUSE_MOVE = "mouse_move"
    KEYBOARD_INPUT = "keyboard_input"
    PLUGIN_ACTION = "plugin_action"
    UI_INTERACTION = "ui_interaction"
    CUSTOM_EVENT = "custom_event"


@dataclass
class OperationRecord:
    """操作记录"""
    id: int
    timestamp: float
    type: OperationType
    plugin_name: str
    action: str
    parameters: Dict[str, Any]
    duration: float = 0.0
    result: Optional[str] = None


class OperationRecorder:
    """操作录制器"""
    
    def __init__(self, max_records: int = 10000):
        self.max_records = max_records
        self._records: List[OperationRecord] = []
        self._recording = False
        self._start_time = 0.0
        self._record_id = 0
        self._lock = threading.RLock()
        self._observers: List[callable] = []
    
    def start_recording(self):
        """开始录制"""
        with self._lock:
            if not self._recording:
                self._recording = True
                self._start_time = time.time()
                self._record_id = 0
                self._records.clear()
    
    def stop_recording(self) -> List[OperationRecord]:
        """停止录制并返回记录"""
        with self._lock:
            if self._recording:
                self._recording = False
                return self._records.copy()
            return []
    
    def is_recording(self) -> bool:
        """检查是否正在录制"""
        return self._recording
    
    def record_operation(self, op_type: OperationType, plugin_name: str, 
                        action: str, parameters: Dict[str, Any], 
                        duration: float = 0.0, result: Optional[str] = None):
        """记录操作"""
        if not self._recording:
            return
        
        with self._lock:
            # 限制记录数量
            if len(self._records) >= self.max_records:
                # 移除最旧的记录
                self._records.pop(0)
            
            self._record_id += 1
            record = OperationRecord(
                id=self._record_id,
                timestamp=time.time() - self._start_time,
                type=op_type,
                plugin_name=plugin_name,
                action=action,
                parameters=parameters,
                duration=duration,
                result=result
            )
            
            self._records.append(record)
            
            # 通知观察者
            for observer in self._observers:
                try:
                    observer(record)
                except:
                    pass
    
    def add_observer(self, observer: callable):
        """添加观察者"""
        with self._lock:
            if observer not in self._observers:
                self._observers.append(observer)
    
    def remove_observer(self, observer: callable):
        """移除观察者"""
        with self._lock:
            if observer in self._observers:
                self._observers.remove(observer)
    
    def clear_records(self):
        """清空记录"""
        with self._lock:
            self._records.clear()
            self._record_id = 0
    
    def get_records(self) -> List[OperationRecord]:
        """获取所有记录"""
        with self._lock:
            return self._records.copy()
    
    def save_to_file(self, file_path: str) -> bool:
        """保存记录到文件"""
        try:
            records_data = []
            for record in self._records:
                record_dict = asdict(record)
                record_dict['type'] = record.type.value
                records_data.append(record_dict)
            
            with open(file_path, 'w', encoding='utf-8') as f:
                json.dump(records_data, f, ensure_ascii=False, indent=2)
            
            return True
        except Exception as e:
            print(f"Error saving records: {e}")
            return False
    
    def load_from_file(self, file_path: str) -> bool:
        """从文件加载记录"""
        try:
            with open(file_path, 'r', encoding='utf-8') as f:
                records_data = json.load(f)
            
            self._records.clear()
            for record_dict in records_data:
                record = OperationRecord(
                    id=record_dict['id'],
                    timestamp=record_dict['timestamp'],
                    type=OperationType(record_dict['type']),
                    plugin_name=record_dict['plugin_name'],
                    action=record_dict['action'],
                    parameters=record_dict['parameters'],
                    duration=record_dict.get('duration', 0.0),
                    result=record_dict.get('result')
                )
                self._records.append(record)
            
            return True
        except Exception as e:
            print(f"Error loading records: {e}")
            return False


class OperationPlayer:
    """操作回放器"""
    
    def __init__(self, recorder: OperationRecorder):
        self.recorder = recorder
        self._playing = False
        self._playback_speed = 1.0
        self._callbacks: Dict[OperationType, callable] = {}
    
    def register_callback(self, op_type: OperationType, callback: callable):
        """注册操作回调函数"""
        self._callbacks[op_type] = callback
    
    def unregister_callback(self, op_type: OperationType):
        """注销操作回调函数"""
        if op_type in self._callbacks:
            del self._callbacks[op_type]
    
    def play(self, records: Optional[List[OperationRecord]] = None, 
             speed: float = 1.0) -> bool:
        """回放操作记录"""
        if self._playing:
            return False
        
        if records is None:
            records = self.recorder.get_records()
        
        if not records:
            return False
        
        self._playing = True
        self._playback_speed = speed
        
        try:
            # 按时间顺序排序
            sorted_records = sorted(records, key=lambda r: r.timestamp)
            
            start_time = time.time()
            for record in sorted_records:
                if not self._playing:
                    break
                
                # 计算等待时间
                elapsed = time.time() - start_time
                wait_time = (record.timestamp / self._playback_speed) - elapsed
                
                if wait_time > 0:
                    time.sleep(wait_time)
                
                # 执行操作
                self._execute_record(record)
            
            return True
        except Exception as e:
            print(f"Error during playback: {e}")
            return False
        finally:
            self._playing = False
    
    def _execute_record(self, record: OperationRecord):
        """执行单个记录"""
        if record.type in self._callbacks:
            try:
                callback = self._callbacks[record.type]
                callback(record.plugin_name, record.action, record.parameters)
            except Exception as e:
                print(f"Error executing record {record.id}: {e}")
    
    def stop(self):
        """停止回放"""
        self._playing = False
    
    def is_playing(self) -> bool:
        """检查是否正在回放"""
        return self._playing


class ScriptGenerator:
    """脚本生成器"""
    
    def __init__(self, recorder: OperationRecorder):
        self.recorder = recorder
    
    def generate_python_script(self, script_name: str = "generated_script") -> str:
        """生成Python脚本"""
        records = self.recorder.get_records()
        if not records:
            return ""
        
        lines = [
            f"# Generated script: {script_name}",
            "# Auto-generated by OperationRecorder",
            "",
            "import time",
            "from plugin_framework.plugin_manager import PluginManager",
            "",
            "def run_script():",
            "    # Initialize plugin manager",
            "    manager = PluginManager('./plugins')",
            "    manager.scan()",
            ""
        ]
        
        # 按时间顺序排序记录
        sorted_records = sorted(records, key=lambda r: r.timestamp)
        
        last_timestamp = 0.0
        for record in sorted_records:
            # 添加延迟
            delay = record.timestamp - last_timestamp
            if delay > 0.001:  # 忽略小于1ms的延迟
                lines.append(f"    time.sleep({delay:.3f})")
            
            # 生成操作代码
            if record.type == OperationType.PLUGIN_ACTION:
                lines.append(f"    # {record.action}")
                lines.append(f"    plugin = manager.get('{record.plugin_name}')")
                lines.append(f"    if plugin:")
                params_str = ", ".join([f"{k}={repr(v)}" for k, v in record.parameters.items()])
                lines.append(f"        plugin.run({params_str})")
            elif record.type == OperationType.CUSTOM_EVENT:
                lines.append(f"    # Custom event: {record.action}")
                lines.append(f"    # Parameters: {record.parameters}")
            
            lines.append("")
            last_timestamp = record.timestamp
        
        lines.append("if __name__ == '__main__':")
        lines.append("    run_script()")
        
        return "\n".join(lines)
    
    def generate_json_script(self) -> str:
        """生成JSON格式的脚本"""
        records = self.recorder.get_records()
        if not records:
            return "{}"
        
        script_data = {
            "version": "1.0",
            "generated_at": time.time(),
            "operations": []
        }
        
        for record in records:
            record_dict = asdict(record)
            record_dict['type'] = record.type.value
            script_data["operations"].append(record_dict)
        
        return json.dumps(script_data, ensure_ascii=False, indent=2)
    
    def save_script(self, file_path: str, format: str = "python") -> bool:
        """保存脚本到文件"""
        try:
            if format.lower() == "python":
                script_content = self.generate_python_script()
            elif format.lower() == "json":
                script_content = self.generate_json_script()
            else:
                raise ValueError(f"Unsupported format: {format}")
            
            with open(file_path, 'w', encoding='utf-8') as f:
                f.write(script_content)
            
            return True
        except Exception as e:
            print(f"Error saving script: {e}")
            return False


# 使用示例
if __name__ == "__main__":
    # 创建录制器
    recorder = OperationRecorder()
    
    # 开始录制
    recorder.start_recording()
    
    # 模拟一些操作
    recorder.record_operation(
        OperationType.PLUGIN_ACTION,
        "hello_plugin",
        "run",
        {"name": "RecorderTest"},
        0.1,
        "Success"
    )
    
    time.sleep(0.5)
    
    recorder.record_operation(
        OperationType.CUSTOM_EVENT,
        "test_plugin",
        "custom_action",
        {"value": 42},
        0.05
    )
    
    # 停止录制
    records = recorder.stop_recording()
    print(f"Recorded {len(records)} operations")
    
    # 生成脚本
    generator = ScriptGenerator(recorder)
    script = generator.generate_python_script("test_recording")
    print("\nGenerated script:")
    print(script)